home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-03 | 30.0 KB | 1,046 lines |
- // copyright 1993 Michael B. Johnson; some portions copyright 1994, MIT
- // see COPYRIGHT for reuse legalities
- //
-
- #import "WW3DShader.h"
- #import <3Dkit/3Dkit.h>
-
- #import "WWShaderArgPointMatrix.h"
- #import "WWEveParser.h"
-
- @implementation WW3DShader
-
- + initialize { return [WW3DShader setVersion:4], self; }
-
- static lightHandleSeed = 0;
-
- static BOOL
- validQuickShader(const char *name)
- {
- if (!name)
- { return NO;
- }
- if (!strcmp("plastic", name))
- { return YES;
- }
- if (!strcmp("paintedplastic", name))
- { return YES;
- }
- if (!strcmp("constant", name))
- { return YES;
- }
- if (!strcmp("matte", name))
- { return YES;
- }
- if (!strcmp("metal", name))
- { return YES;
- }
- if (!strcmp("shinymetal", name))
- { return YES;
- }
- if (!strcmp("ambientlight", name))
- { return YES;
- }
- if (!strcmp("distantlight", name))
- { return YES;
- }
- if (!strcmp("pointlight", name))
- { return YES;
- }
- if (!strcmp("spotlight", name))
- { return YES;
- }
- if (!strcmp("depthcue", name))
- { return YES;
- }
- if (!strcmp("fog", name))
- { return YES;
- }
- if (!strcmp("bumpy", name))
- { return YES;
- }
- return NO;
- }
-
- - init
- {
- if (![super init])
- { return nil;
- }
-
- // for each of the tokens, we need to see if it corresponds to a
- // valid argument of this shader. If it does, we set the value
- // using the corresponding parm.
- n = 0;
- tokens = NULL;
- parms = NULL;
- archiveVector = NULL;
- printfNVector = NULL;
- printfTypeVector = NULL;
- iconImage = [NXImage findImageNamed:"shader"];
- [self assignQuickShader];
- usingSupportedQRManShader = NO;
-
- lightHandle = 0;
-
- // dis ain't dat portable, ya know...
- ribColor[0] = 1.0;
- ribColor[1] = 1.0;
- ribColor[2] = 1.0;
-
- return self;
- }
-
-
- - (BOOL)pushesOrPopsCTM { return NO; }
- - (BOOL)pushesCTM { return NO; }
- - (BOOL)popsCTM { return NO; }
-
- - initWithShader:(const char *)shaderName n:(int)newN tokens:(RtToken *)newTokens parms:(RtPointer *)newParms archiveVector:(char **)newArchiveVector printfTypeVector:(int *)newPrintfTypeVector printfNVector:(int *)newPrintfNVector
- {
- int i;
-
-
- if (![super initWithShader:shaderName])
- { return nil;
- }
-
- [self setShader:shaderName];
- [self setUseColor:NO];
-
- // for each of the tokens, we need to see if it corresponds to a
- // valid argument of this shader. If it does, we set the value
- // using the corresponding parm.
- n = newN;
- tokens = newTokens;
- parms = newParms;
- archiveVector = newArchiveVector;
- printfNVector = (int *)malloc(n * sizeof(int));
- printfTypeVector = (int *)malloc(n * sizeof(int));
-
- for (i = 0; i < n; i++)
- { if (![self setShaderArgNamed:tokens[i] withValue:parms[i]])
- { NXLogError("in shader %s, <%s> is not a valid arg.\n",
- shaderName, tokens[i]);
- }
- printfNVector[i] = newPrintfNVector[i];
- printfTypeVector[i] = newPrintfTypeVector[i];
- }
-
- lightHandle = 0;
-
- // dis ain't dat portable, ya know...
- ribColor[0] = 1.0;
- ribColor[1] = 1.0;
- ribColor[2] = 1.0;
-
- return self;
- }
-
- - setShader:(const char *)name
- {
- if (![super setShader:name])
- { return nil;
- }
- if (name)
- { iconImage = [NXImage findImageNamed:(char *)name];
- }
- else
- { iconImage = nil;
- }
- if (!iconImage)
- { iconImage = [NXImage findImageNamed:"shader"];
- }
- if (validQuickShader(name))
- { quickShader = NXCopyStringBuffer(name);
- usingSupportedQRManShader = YES;
- }
- else
- { [self assignQuickShader];
- usingSupportedQRManShader = NO;
- }
-
- return self;
- }
-
- - assignQuickShader
- {
- if (quickShader) { free(quickShader); }
- switch ([self shaderType])
- {
- case SLO_TYPE_SURFACE:
- // really should be arbitrarily smart here
- // you can look at the parameters of the shaders, etc. to try and figure out which it use
- // for now, just just use plastic.
- quickShader = NXCopyStringBuffer("plastic");
- break;
-
- case SLO_TYPE_LIGHT:
- quickShader = NXCopyStringBuffer("pointlight");
- break;
-
- case SLO_TYPE_DISPLACEMENT:
- quickShader = NXCopyStringBuffer("bumpy");
- break;
-
- case SLO_TYPE_VOLUME:
- // need to figure out what kind...
- quickShader = NXCopyStringBuffer("depthcue");
- break;
-
- case SLO_TYPE_TRANSFORMATION:
- quickShader = NULL;
- break;
-
- case SLO_TYPE_IMAGER:
- quickShader = NULL;
- break;
-
- default:
- quickShader = NULL;
- return nil;
- }
-
- return self;
- }
-
- - setShaderArgNamed:(const char *)argName withValue:(RtPointer)value
- {
- SLO_TYPE argType;
-
-
- argType = [self shaderArgType:argName];
- if (argType == SLO_TYPE_POINT)
- { return [self setShaderArg:argName pointValue:*((RtPoint *)value)];
- }
- if (argType == SLO_TYPE_COLOR)
- { // note that it wants an NXColor, not an RtColor...
- RtFloat r = *((RtFloat *)value);
- RtFloat g = *((RtFloat *)(value+sizeof(RtFloat)));
- RtFloat b = *((RtFloat *)(value+(2*sizeof(RtFloat))));
- NXColor anNXColor = NXConvertRGBToColor((float)r, (float)g, (float)b);
-
- return [self setShaderArg:argName colorValue:anNXColor];
- }
- if (argType == SLO_TYPE_SCALAR)
- { return [self setShaderArg:argName floatValue:(*((RtFloat *)value))];
- }
- if (argType == SLO_TYPE_STRING)
- { return [self setShaderArg:argName stringValue:(*(char **)value)];
- }
-
- return nil;
- }
-
-
- - (const char *)quickShader { return quickShader; }
- - setQuickShader:(const char *)newQuickShader
- {
- if (!validQuickShader(newQuickShader))
- { NXLogError("%s is not a shader supported by qrman, yabba-head!\n");
- return nil;
- }
- if (quickShader)
- { free(quickShader);
- }
- quickShader = NXCopyStringBuffer(newQuickShader);
- return self;
- }
-
- - setColor:(NXColor)aColor
- {
- ribColor[0] = NXRedComponent(aColor);
- ribColor[1] = NXGreenComponent(aColor);
- ribColor[2] = NXBlueComponent(aColor);
- return [super setColor:aColor];
- }
-
- - (RtToken)token { return token; }
-
- - setToken:(RtToken)newToken
- {
- token = newToken;
- return self;
- }
-
- - set
- {
- if (NXDrawingStatus == NX_DRAWING)
- {
- if ([self doesUseColor])
- { RiColor(ribColor);
- }
- if (quickShader)
- { switch ([self shaderType])
- {
- case SLO_TYPE_SURFACE:
- RiSurfaceV(quickShader, n, tokens, parms);
- break;
-
- case SLO_TYPE_LIGHT:
- if (!token)
- { RiCreateHandle(token, RI_LIGHTSOURCE);
- }
- if (pointOrArea)
- { lightHandle = RiAreaLightSourceV(token, quickShader, n, tokens, parms);
- }
- else
- { lightHandle = RiLightSourceV(token, quickShader, n, tokens, parms);
- }
- break;
-
- default:
- break;
- }
- }
- }
- else
- {
- [super set];
- }
-
- return self;
- }
-
- // WWRenderable
-
- - (BOOL)hasBoundingBox { return NO; }
- - calculateBoundingBoxStartingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime { return self; }
-
- - renderMaps:(WW3DCamera *)camera startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime usingStream:(NXStream *)ns
- {
- return self;
- }
- - renderMaps:(WW3DCamera *)camera usingStream:(NXStream *)ns
- {
- return self;
- }
-
- - renderMaps:(WW3DCamera *)camera startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
- {
- return self;
- }
- - renderMaps:(WW3DCamera *)camera
- {
- return self;
- }
-
- - setAtmosphere { volumeType = WW_ATMOSPHERE; return self; }
- - setInterior { volumeType = WW_INTERIOR; return self; }
- - setExterior { volumeType = WW_EXTERIOR; return self; }
- - setPointSource { pointOrArea = 0; return self; }
- - setAreaSource { pointOrArea = 1; return self; }
-
- - renderSelfAsBox:(WW3DCamera *)camera startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
- { return [self renderSelf:camera startingAt:shutterOpenTime endingAt:shutterCloseTime];
- }
-
- - renderSelf:(WW3DCamera *)camera startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
- {
- switch ([self shaderType])
- {
- case SLO_TYPE_SURFACE:
- RiSurfaceV((char *)[self shader], n, tokens, parms);
- break;
-
- case SLO_TYPE_LIGHT:
- if (!token) { RiCreateHandle(token, RI_LIGHTSOURCE); }
- if (pointOrArea)
- { lightHandle = RiAreaLightSourceV(token, (char *)[self shader], n, tokens, parms);
- }
- else
- { lightHandle = RiLightSourceV(token, (char *)[self shader], n, tokens, parms);
- }
- break;
-
- case SLO_TYPE_DISPLACEMENT:
- RiDisplacementV((char *)[self shader], n, tokens, parms);
- break;
-
- case SLO_TYPE_VOLUME:
- switch (volumeType)
- { case WW_ATMOSPHERE: RiAtmosphereV((char *)[self shader], n, tokens, parms);
- break;
- case WW_INTERIOR: RiInteriorV((char *)[self shader], n, tokens, parms);
- break;
- case WW_EXTERIOR: RiExteriorV((char *)[self shader], n, tokens, parms);
- break;
- default: NXLogError("unknown volume shader %s!\n", (char *)[self shader]);
- }
- break;
-
- case SLO_TYPE_TRANSFORMATION:
- NXLogError("warning: using RiDeformationV for Transformation shader %s...\n", [self shader]);
- RiDeformationV((char *)[self shader], n, tokens, parms);
- break;
-
- case SLO_TYPE_IMAGER:
- RiImagerV((char *)[self shader], n, tokens, parms);
- break;
-
- default:
- return nil;
- }
- return self;
- }
-
- - renderSelf:(WW3DCamera *)camera
- {
- RtFloat shutterOpenTime = [camera shutterOpenTime],
- shutterCloseTime = [camera shutterCloseTime];
-
-
- return [self renderSelf:camera startingAt:shutterOpenTime endingAt:shutterCloseTime];
- }
-
- // this is a tough one; should the shader prerender itself? For some shaders, especially ones
- // that make holes in objects, the answer is probably yes, but for those that are merely complicated
- // texturers, they shouldn't. Probably best to keep a flag around to decide...
- // for now, just render
- - preRenderSelf:(WW3DCamera *)camera startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
- {
- return [self renderSelf:camera startingAt:shutterOpenTime endingAt:shutterCloseTime];
- }
-
- - preRenderSelf:(WW3DCamera *)camera
- {
- return [self renderSelf:camera];
- }
-
- - transformCTM:(WW3DAttributeState *)attributeState startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime { return self; }
-
- - setBoundingBox:(RtBound *)newBoundingBox { return nil; }
- - (RtBound *)boundingBoxStartingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime { return (RtBound *)NULL; };
-
- - (void)setN:(int)newN tokens:(RtToken *)newTokens parms:(RtPointer *)newParms archiveVector:(char **)newArchiveVector printfTypeVector:(int *)newPrintfTypeVector printfNVector:(int *)newPrintfNVector
- {
- int i;
-
-
- if (n)
- { for (i = 0; i < n; i++)
- { // don't free the tokens; they're shared!
- free(parms[i]);
- free(archiveVector[i]);
- free(printfNVector);
- free(printfTypeVector);
- }
- if (newN > n)
- { tokens = (RtToken *)NXZoneRealloc([self zone], tokens, (newN * sizeof(RtToken)));
- parms = (RtPointer *)NXZoneRealloc([self zone], parms, (newN * sizeof(RtPointer)));
- archiveVector = (char **)NXZoneRealloc([self zone], archiveVector, (newN * sizeof(archiveVector)));
- printfNVector = (int *)NXZoneRealloc([self zone], printfNVector, (newN * sizeof(int)));
- printfTypeVector = (int *)NXZoneRealloc([self zone], printfTypeVector, (newN * sizeof(int)));
- }
- }
- else
- { tokens = (RtToken *)NXZoneMalloc([self zone], newN * sizeof(RtToken));
- parms = (RtPointer *)NXZoneMalloc([self zone], newN * sizeof(RtPointer));
- archiveVector = (char **)NXZoneMalloc([self zone], newN * sizeof(archiveVector));
- printfNVector = (int *)NXZoneMalloc([self zone], newN * sizeof(int));
- printfTypeVector = (int *)NXZoneMalloc([self zone], newN * sizeof(int));
- }
- n = newN;
- for (i = 0; i < n; i++)
- { tokens[i] = newTokens[i];
- parms[i] = newParms[i];
- archiveVector[i] = newArchiveVector[i];
- printfNVector[i] = newPrintfNVector[i];
- printfTypeVector[i] = newPrintfTypeVector[i];
- }
-
- return ;
- }
-
- - (int)n { return n; }
- - (RtToken *)tokens { return tokens; }
- - (RtPointer *)parms { return parms; }
- - (char **)archiveVector { return archiveVector; }
- - (int *)printfNVector { return printfNVector; }
- - (int *)printfTypeVector { return printfTypeVector; }
-
- // should make this lerpable, but later...
- - (BOOL)isLerpable { return YES; }
-
- // this should only be called internally
- // the receiving object needs to copy all the parameters using the passed in zone
- // the assumption is that
- - _mallocPointersForN:(int)newN usingZone:(NXZone *)newZone
- {
- n = newN;
- if (n)
- { tokens = (RtToken *)NXZoneMalloc([self zone], n * sizeof(RtToken));
- if (!tokens)
- { return nil;
- }
- parms = (RtPointer *)NXZoneMalloc([self zone], n * sizeof(RtPointer));
- if (!parms)
- { NXZoneFree(newZone, tokens);
- return nil;
- }
- archiveVector = (char **)NXZoneMalloc([self zone], n * sizeof(char *));
- if (!archiveVector)
- { NXZoneFree(newZone, tokens);
- NXZoneFree(newZone, parms);
- return nil;
- }
- printfNVector = (int *)NXZoneMalloc([self zone], n * sizeof(int));
- if (!printfNVector)
- { NXZoneFree(newZone, tokens);
- NXZoneFree(newZone, parms);
- NXZoneFree(newZone, archiveVector);
- return nil;
- }
- printfTypeVector = (int *)NXZoneMalloc([self zone], n * sizeof(int));
- if (!printfTypeVector)
- { NXZoneFree(newZone, tokens);
- NXZoneFree(newZone, parms);
- NXZoneFree(newZone, archiveVector);
- NXZoneFree(newZone, printfNVector);
- return nil;
- }
- }
- else
- { // n == 0
- tokens = (RtToken *)NULL;
- parms = (RtPointer *)NULL;
- archiveVector = (char **)NULL;
- printfNVector = (int *)NULL;
- printfTypeVector = (int *)NULL;
- }
- return self;
- }
-
- - _setToken:(char *)newToken parm:(RtPointer)newParm i:(int)i archiveInfo:(char *)archiveInfo type:(int)parmType count:(int)howMany usingZone:(NXZone *)newZone
- {
- int j;
-
-
- tokens[i] = (RtToken)NXZoneMalloc(newZone, (1 + strlen(newToken)));
- if (!tokens[i])
- { return nil;
- }
- strcpy(tokens[i], newToken);
-
- archiveVector[i] = (char *)NXZoneMalloc(newZone, (1 + strlen(archiveInfo)));
- if (!archiveVector[i])
- { NXZoneFree(newZone, tokens[i]);
- return nil;
- }
- strcpy(archiveVector[i], archiveInfo);
-
- printfTypeVector[i] = parmType;
- printfNVector[i] = howMany;
-
- // in a perfect world, I could just copy that chunk o memory over,
- // but I'm worried about alignment problems, so I'll do it the slow way...
- switch (printfTypeVector[i])
- { case WW_FLOAT: parms[i] = (RtFloat *)NXZoneMalloc(newZone, sizeof(RtFloat) * howMany);
- for (j = 0; j < printfNVector[i]; j++)
- { *((RtFloat *)parms[i] + j) = *((RtFloat *)(newParm) + j);
- }
- break;
- case WW_COLOR: parms[i] = (RtFloat *)NXZoneMalloc(newZone, sizeof(RtFloat) * howMany);
- for (j = 0; j < printfNVector[i]; j++)
- { *((RtFloat *)parms[i] + j) = *((RtFloat *)(newParm) + j);
- }
- break;
- case WW_POINT: parms[i] = (RtFloat *)NXZoneMalloc(newZone, sizeof(RtFloat) * howMany);
- for (j = 0; j < printfNVector[i]; j++)
- { *((RtFloat *)parms[i] + j) = *((RtFloat *)(newParm) + j);
- }
- break;
- case WW_INT: parms[i] = (int *)NXZoneMalloc(newZone, sizeof(int) * howMany);
- for (j = 0; j < printfNVector[i]; j++)
- { *((int *)parms[i] + j) = *((int *)(newParm) + j);
- }
- break;
- // hmm, strings are weirder.
- case WW_STRING: parms[i] = (char **)NXZoneMalloc(newZone, sizeof(char *) * howMany);
- for (j = 0; j < printfNVector[i]; j++)
- { // need to additionally malloc up some memory here, folks
- *((char **)parms[i] + j) = (char *)NXZoneMalloc(newZone, (1 + strlen(*((char **)(newParm) + j))));
- strcpy(*((char **)parms[i] + j), *((char **)(newParm) + j));
- }
- break;
- }
- return self;
- }
-
-
- - copyFromZone:(NXZone *)newZone
- {
- int i;
- //id newCopy = [super copyFromZone:newZone];
- id newCopy = [(WW3DShader *)[[WW3DShader alloc] init] setShader:[self shader]];
-
-
- // now we need to grovel over the parameters and copy them
- // this is a pain, but boy, will it be cool...
- // okay, malloc up the base list of pointers
- [newCopy _mallocPointersForN:n usingZone:newZone];
- [newCopy setToken:[self token]];
-
- for (i = 0; i < n; i++)
- { if (![newCopy _setToken:tokens[i] parm:parms[i] i:i
- archiveInfo:archiveVector[i] type:printfTypeVector[i] count:printfNVector[i]
- usingZone:newZone])
- { [newCopy free];
- return nil;
- }
- }
-
- return newCopy;
- }
-
- - _lerpParametersWith:b by:(float)u
- {
- int i, j;
- RtToken *tokensB;
- char **archiveVectorB;
- int *printfNVectorB;
- int *printfTypeVectorB;
- RtPointer *parmsB;
-
-
- // okay, first thing to realize is that this instance already has its
- // parameters set to the (u ==0) case here. Therefore, when in doubt,
- // you can leave it alone and you're fine. We now want to grovel
- // over the two objects' parameters.
- if (n != [b n])
- { // hmm. looks like trouble. At some point, we'll have to bail,
- // since the parameter lists aren't the same length. we could
- // bail right away, since we know that "self"'s parameters are set
- // to something reasonable... Yea, let's bail.
- return self;
- }
-
- tokensB = [b tokens];
- archiveVectorB = [b archiveVector];
- printfNVectorB = [b printfNVector];
- printfTypeVectorB = [b printfTypeVector];
- parmsB = [b parms];
-
- // okay, at this point, we know that these two objects are the same
- // class, and the length of their parameter lists are the same. Of
- // course, this might be just a lucky coincidence, and the actual
- // parameters might be different types.
-
- for (i = 0; i < n; i++)
- { if ((tokens[i] == tokensB[i]) || (!strcmp(tokens[i], tokensB[i])))
- { // great! they're the same token.
- // now we need to make sure they're the same type and length of data
- // if not, bail to the next parameter
- if ((printfNVector[i] == printfNVectorB[i]) && (printfTypeVector[i] == printfTypeVectorB[i]))
- { // okay! we're golden. Let's do a lerp...
- switch (printfTypeVector[i])
- { case WW_FLOAT: for (j = 0; j < printfNVector[i]; j++)
- { *((RtFloat *)parms[i] + j) += ((*((RtFloat *)(parmsB[i]) + j) - *((RtFloat *)parms[i] + j)) * u);
- }
- break;
- case WW_COLOR: for (j = 0; j < printfNVector[i]; j++)
- { *((RtFloat *)parms[i] + j) += ((*((RtFloat *)(parmsB[i]) + j) - *((RtFloat *)parms[i] + j)) * u);
- }
- break;
- case WW_POINT: for (j = 0; j < printfNVector[i]; j++)
- { *((RtFloat *)parms[i] + j) += ((*((RtFloat *)(parmsB[i]) + j) - *((RtFloat *)parms[i] + j)) * u);
- }
- break;
- case WW_INT: for (j = 0; j < printfNVector[i]; j++)
- { *((int *)parms[i] + j) += ((*((int *)(parmsB[i]) + j) - *((int *)parms[i] + j)) * u);
- }
- break;
- case WW_STRING: // can't lerp strings without more info...
- // maybe could encode a way to do it with enumerated values, but for now, bail...
- break;
- }
- }
- else
- { // okay, that parameter can't be lerp'ed; on to the next
- }
- }
- else
- { // okay, that parameter can't be lerp'ed; on to the next
- }
- }
-
- // all right, we've lerped our parameters, now we need to "install" them in the shader...
- for (i = 0; i < n; i++)
- { if (![self setShaderArgNamed:tokens[i] withValue:parms[i]])
- { NXLogError("in shader %s, <%s> is not a valid arg.\n",
- [self shader], tokens[i]);
- }
- }
-
- return self;
- }
-
-
- // note: because we've made the WWSampleList "safe" for having
- // multiple samples with the same data, it's perfectly valid to return
- // yourself or b
- - lerpWith:b by:(float)uValue
- {
- id newMe = nil;
-
-
- if (([self class] != [b class]) || (uValue <= 0.0) || (![self shader]) || (![b shader]) || (strcmp([self shader], [b shader])))
- { return self;
- }
-
- if (uValue >= 1.0)
- { return b;
- }
-
- newMe = [self copyFromZone:[self zone]];
-
- // okay, now we have to get newMe to linearly interpolate it
- // parameters partway between "self" and "b"
- [newMe _lerpParametersWith:b by:uValue];
-
- return newMe;
- }
-
- - lerpSelfWith:b by:(float)uValue
- {
- if (([self class] != [b class]) || (uValue <= 0.0) || (![self shader]) || (![b shader]) || (strcmp([self shader], [b shader])))
- { return self;
- }
-
- if (uValue >= 1.0)
- { return b;
- }
-
- // okay, now we have to get newMe to linearly interpolate it
- // parameters partway between "self" and "b"
- [self _lerpParametersWith:b by:uValue];
-
- return self;
- }
-
-
- // in 3.4, shaders aren't motion blurrable
- - (BOOL)isMotionBlurrable { return NO; }
- - (BOOL)isCompoundCommand { return NO; }
-
- // stuff for 3DReality, as well as general UI expansion
-
- - setIconImage:image { iconImage = image; return self; }
-
- - setIconImageNamed:(const char *)name
- { // It's actually a bad idea to free this image, because it might be shared...
- if (name && *name)
- { iconImage = [NXImage findImageNamed:name];
- if (!iconImage)
- { iconImage = [[NXImage alloc] init];
- // [iconImage setDataRetained:YES];
- if (![iconImage loadFromFile:name])
- { NXLogError("unable to load image from file <%s>\n", name);
- return nil;
- }
- }
- }
- return self;
- }
-
- - iconImage { return iconImage; }
-
-
- // target/action messages
- - takeColorArg:sender
- {
- [self setShaderArg:[sender shaderArgName] colorValue:[sender color]];
- return self;
- }
-
- - takeFloatArg:sender
- {
- [self setShaderArg:[sender shaderArgName] floatValue:[sender floatValue]];
- return self;
- }
-
- - takePointArg:sender
- {
- RtPoint aPoint;
-
- N3D_XComp(aPoint) = [[sender cellAt:0 :0] floatValue];
- N3D_YComp(aPoint) = [[sender cellAt:0 :1] floatValue];
- N3D_ZComp(aPoint) = [[sender cellAt:0 :2] floatValue];
- [self setShaderArg:[sender shaderArgName] pointValue:aPoint];
- return self;
- }
-
- - takeStringArg:sender
- {
- [self setShaderArg:[sender shaderArgName] stringValue:[sender stringValue]];
- return self;
- }
-
-
- // WavesWorld archiving:
- // writeEve:(NXStream *)stream
- // writeScene:(NXStream *)stream
-
- // this is a routine for subclasses to call when archiving themselves to an eve file or a scene...
- - writeParameterList:(NXStream *)stream
- {
- int i, j;
-
-
- if (!n)
- { NXPrintf(stream, ";");
- return nil;
- }
- for (i = 0; i < n; i++)
- { NXPrintf(stream, "{%s} ", tokens[i]);
- NXPrintf(stream, "{ ");
- switch (printfTypeVector[i])
- { case WW_FLOAT: for (j = 0; j < printfNVector[i]; j++)
- { NXPrintf(stream, "%f ", *((RtFloat *)(parms[i]) + j));
- }
- break;
- case WW_COLOR: for (j = 0; j < printfNVector[i]; j++)
- { NXPrintf(stream, "%f ", *((RtFloat *)(parms[i]) + j));
- }
- break;
- case WW_POINT: for (j = 0; j < printfNVector[i]; j++)
- { NXPrintf(stream, "%f ", *((RtFloat *)(parms[i]) + j));
- }
- break;
- case WW_INT: for (j = 0; j < printfNVector[i]; j++)
- { NXPrintf(stream, "%d ", *((int *)(parms[i]) + j));
- }
- break;
- case WW_STRING: for (j = 0; j < printfNVector[i]; j++)
- { NXPrintf(stream, "{%s} ", *((char **)(parms[i]) + j));
- }
- break;
- }
- NXPrintf(stream, "} ");
- }
- NXPrintf(stream, ";");
- return self;
- }
-
- - writeEve:(NXStream *)stream atTabLevel:(int)tab
- {
- int i;
-
-
- for (i = 0; i < tab; i++)
- { NXPrintf(stream, "\t");
- }
-
- switch ([self shaderType])
- {
- case SLO_TYPE_SURFACE:
- NXPrintf(stream, "Surface %s ", shader);
- break;
-
- case SLO_TYPE_LIGHT:
- if (!lightHandle)
- { lightHandleSeed++;
- lightHandle = (char *)malloc(64);
- sprintf(lightHandle, "%d", lightHandleSeed);
- }
- if (pointOrArea)
- { NXPrintf(stream, "AreaLightSource %s %s ", shader, lightHandle);
- }
- else
- { NXPrintf(stream, "LightSource %s %s ", shader, lightHandle);
- }
- break;
-
- case SLO_TYPE_DISPLACEMENT:
- NXPrintf(stream, "Displacement %s ", shader);
- break;
-
- case SLO_TYPE_VOLUME:
- switch (volumeType)
- { case WW_ATMOSPHERE: NXPrintf(stream, "Atmosphere %s ", shader);
- break;
- case WW_INTERIOR: NXPrintf(stream, "Interior %s ", shader);
- break;
- case WW_EXTERIOR: NXPrintf(stream, "Exterior %s ", shader);
- break;
- default: NXLogError("# unknown volume shader %s ", (char *)[self shader]);
- }
-
- break;
-
- case SLO_TYPE_TRANSFORMATION:
- NXPrintf(stream, "Deformation %s ", shader);
- break;
-
- case SLO_TYPE_IMAGER:
- NXPrintf(stream, "Imager %s ", shader);
- break;
-
- default:
- NXPrintf(stream, "# unknown shader %s ", shader);
- return nil;
- }
-
- [self writeParameterList:stream];
-
- return self;
- }
-
- - writeScene:(NXStream *)stream atTabLevel:(int)tab
- {
- return [self writeEve:stream atTabLevel:tab];
- }
-
- - write3DTextScene:(NXStream *)stream atTabLevel:(int)tab index:(int)index time:(float)time until:(float)lastTime
- {
- int i;
-
-
- for (i = 0; i < tab; i++)
- { NXPrintf(stream, "\t");
- }
-
- NXPrintf(stream, "startShape %s; ", [[self class] name]);
- // need tab
- // need index (position in current list)
- NXPrintf(stream,
- "EveCmd {Translate [expr { %d * $__text__(tabLength)}] [expr {$__text__(spacingFactor) * %d * $__text__(spacing) * $__text__(fontSize)}] 0 };\n",
- tab, index);
- NXPrintf(stream, " EveCmd {WW3DText $__text__(fontName) $__text__(fontSize) {");
- [self writeEve:stream atTabLevel:tab];
- NXPrintf(stream, "} left;}\n");
- NXPrintf(stream, "endShape;\n");
-
- return self;
- }
-
-
- - writeInventorAtTime:(float)currentTime to:(NXStream *)stream atTabLevel:(int)tab
- {
- int i;
-
-
- for (i = 0; i < tab; i++)
- { NXPrintf(stream, "\t");
- }
- NXPrintf(stream, "# WW3DShader %s called;", [self shader]);
- return self;
-
- }
-
- // NeXTSTEP archiving:
-
- #define typeVectorVersion1 "i"
- #define typeValuesVersion1 &n
-
- #define typeVector "i@"
- #define typeValues &n, &iconImage
-
- - read:(NXTypedStream*)stream
- {
- int version, i;
-
-
- [super read:stream];
-
- version = NXTypedStreamClassVersion(stream,"WW3DShader");
- if (version == 0) NXReadTypes(stream,"i",&version), version=1;
- if (version == 1)
- { NXReadTypes(stream, typeVectorVersion1, typeValuesVersion1);
- tokens = (char **)NXZoneMalloc([self zone], (sizeof(char *) * n));
- archiveVector = (char **)NXZoneMalloc([self zone], (sizeof(char *) * n));
- parms = (RtPointer *)NXZoneMalloc([self zone], (sizeof(char *) * n));
- for (i = 0; i < n; i++)
- { NXReadTypes(stream, "**", &(tokens[i]), &(archiveVector[i]));
- NXReadTypes(stream, archiveVector[i], &(parms[i]));
- }
- }
- if (version == 2)
- { NXReadTypes(stream, typeVector, typeValues);
- tokens = (char **)NXZoneMalloc([self zone], (sizeof(char *) * n));
- archiveVector = (char **)NXZoneMalloc([self zone], (sizeof(char *) * n));
- parms = (RtPointer *)NXZoneMalloc([self zone], (sizeof(char *) * n));
- for (i = 0; i < n; i++)
- { NXReadTypes(stream, "**", &(tokens[i]), &(archiveVector[i]));
- NXReadTypes(stream, archiveVector[i], &(parms[i]));
- }
- }
- if (version == 3)
- { NXReadTypes(stream, typeVector, typeValues);
- tokens = (char **)NXZoneMalloc([self zone], (sizeof(char *) * n));
- archiveVector = (char **)NXZoneMalloc([self zone], (sizeof(char *) * n));
- parms = (RtPointer *)NXZoneMalloc([self zone], (sizeof(char *) * n));
- for (i = 0; i < n; i++)
- { NXReadTypes(stream, "**", &(tokens[i]), &(archiveVector[i]));
- NXReadTypes(stream, archiveVector[i], &(parms[i]));
- }
- NXReadTypes(stream, "*ic", &quickShader, &lightHandle, &usingSupportedQRManShader);
- NXReadArray(stream, "f", 3, ribColor);
- }
- if (version == 4)
- { NXReadTypes(stream, typeVector, typeValues);
- tokens = (char **)NXZoneMalloc([self zone], (sizeof(char *) * n));
- archiveVector = (char **)NXZoneMalloc([self zone], (sizeof(char *) * n));
- parms = (RtPointer *)NXZoneMalloc([self zone], (sizeof(char *) * n));
- for (i = 0; i < n; i++)
- { NXReadTypes(stream, "**", &(tokens[i]), &(archiveVector[i]));
- NXReadTypes(stream, archiveVector[i], &(parms[i]));
- }
- NXReadTypes(stream, "*ic", &quickShader, &lightHandle, &usingSupportedQRManShader);
- NXReadArray(stream, "f", 3, ribColor);
- NXReadTypes(stream, "ic", &volumeType, &pointOrArea);
- }
-
- return self;
- }
-
- - write:(NXTypedStream*)stream
- {
- int i;
-
-
- [super write:stream];
-
- NXWriteTypes(stream,typeVector, typeValues);
- for (i = 0; i < n; i++)
- { NXWriteTypes(stream, "**", &(tokens[i]), &(archiveVector[i]));
- NXWriteTypes(stream, archiveVector[i], &(parms[i]));
- }
- NXWriteTypes(stream, "*ic", &quickShader, &lightHandle, &usingSupportedQRManShader);
- NXWriteArray(stream, "f", 3, ribColor);
- NXWriteTypes(stream, "ic", &volumeType, &pointOrArea);
-
- return self;
- }
-
- // boy, this is dumb... This is to get around the stupid warnings from the compiler - ask wave for details
- - class { return [super class]; }
-
- - (float)lastSampleIsAt { return 0.0; }
-
- - (BOOL)isMoot
- {
- return NO;
- }
-
- - (BOOL)isMootStartingAt:(float)startTime endingAt:(float)endTime { return [self isMoot]; }
-
- - (BOOL)theSameAs:otherRIBCommand
- {
- return NO;
- }
-
- - (BOOL)similarTo:otherRIBCommand
- {
- if ([self class] != [otherRIBCommand class])
- { return NO;
- }
- return YES;
- }
-
-
- //WAVE FIX ME!!!
- - (unsigned long int)maxSampleBandwidth { return 100; }
-
- @end
-